#define _CRT_SECURE_NO_WARNINGS 1

// 栈区：stack在执行函数时，函数内局部变量的存储单元都可以在栈上创建
//      函数执行结束时候这些存储单元自动被释放
//      栈内存分配运算内置于处理器的指令集中，效率很高，但是分配的内存空间很有限
//      栈区主要存放运行函数而分配的局部变量，函数参数、返回数据、返回地址
// 堆区：一般由程序员分配释放，若程序员不释放，程序结束时可能由OS回收
// 数据段（静态区）：存放全局变量、静态数据。 程序结束后由系统释放
// 代码段：存放函数体（类成员函数和全局函数）的二进制代码


// 文件操作

// 为什么使用文件？
// 如果没有文件，我们写的程序的数据是存储在电脑的内存中，如果程序退出，内存回收
// 数据就丢失了，等再次运行程序，是看不到上次程序的数据的
// 如果要将数据进行持久化的保存，我们可以使用文件

// 什么是文件？
// 磁盘（硬盘）上的文件是文件
// 但是在程序设计中，我们一般谈的文件有两种：程序文件、数据文件（从文件功能的角度来分类的）

// 程序文件
// 包括源程序文件（后缀为.c），目标文件（windows环境后缀为.obj），可执行程序（windows环境后缀为.exe）

// 数据文件
// 文件的内容不一定是程序，而是程序运行时读写的数据，比如程序运行需要从中读取数据的文件，或者输出内容的文件
// 在以前各章所处理数据的输入输出都是以终端为对象的，即从终端的键盘输入数据，运行结果显示道显示器上
// 其实有时候我们会把信息输出到磁盘上，当需要的时候再从磁盘上把数据读取到内存中使用，这里处理的就是磁盘上文件

// 文件名
// 一个文件要有一个唯一的文件标识，以便用户识别和运行

// 二进制文件和文本文件
// 整数10000，如果以ASCII码的形式输出到磁盘，则磁盘中占用5个字节（每个字符一个字节）
// 而二进制形式输出，则在磁盘上只占4个字节

//#include <stdio.h>

// 在VS上采取二进制编辑器打开
//int main()
//{
//	int a = 10000;
//
//	FILE* pf = fopen("text.txt", "wb");
//	fwrite(&a, 4, 1, pf); // 二进制的形式写到文件中
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

// 操作文件
// 1.打开文件
// 2.读或者写文件
// 3.关闭文件

// 文件的打开和关闭
// 流和标准流
// 什么是流？
// 我们程序的数据需要输出到各种外部设备上，也需要从外部设备获取数据
// 不同外部设备的输入输出操作各不相同，因此只需要关心流就可以

// C语言程序在启动的时候，就默认打开了3个流
// 流的类型是FILE*

// 文件指针
// 每个被使用的文件都在内存中开辟了一个相应的文件信息区，用来存放文件的相关信息
// 这些信息是保存在一个结构体变量中的，且由系统声明，名字叫做FILE

// 每当打开一个文件的时候，系统会根据文件的情况自动创建一个FILE结构的变量
// 并填充其中的信息

// 通过文件指针变量能够间接找到与它关联的文件。

// 文件的打开和关闭
// 文件在读写之前应该先打开文件，在使用结束之后应该关闭文件
// FILE* fopen(const char* filename, const char* mode);
// int fclose(FILE* stream);

//#include <stdio.h>
//
//int main()
//{
//	// 打开文件：为了写
//	
//	// 如果文件打开失败，会返回一个空指针
////	// FILE* pf = fopen("C:\\Users\\zpeng\\Desktop\\data.txt", "w");
////	//. 表示当前目录
////	//.. 表示上一级路径
////	//FILE* pf = fopen("./../../data.txt", "w");
//
//	// 如果没有，新建一个，如果有，重新建一个
//	FILE* pf = fopen("data.txt", "w");
//	if (pf == NULL) {
//		perror("fopen");
//		return 1;
//	}
//	// 写文件
//
//	// 关闭文件
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

// 顺序读写函数介绍
// fgetc字符输入函数适合所有输入流
// fputc字符输出函数适合所有输出流

// fgets文本行输入函数适合所有输入流
// fputs文本行输出函数适合所有输出流

// fscanf格式化输入函数适合所有输入流
// fprintf格式化输出函数适合所有输出流

// fread二进制输入适合文本输入流
// fwrite二进制输出适合文本输出流

//#include <stdio.h>
//
//int main()
//{
//	// 打开文件
//	FILE* pf = fopen("data.txt", "r");
//
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//
//	// 读文件
//	int ch = fgetc(pf); // a
//	printf("%c\n", ch);
//
//	ch = fgetc(pf); // b
//	printf("%c\n", ch);
//
//	ch = fgetc(pf); // c
//	printf("%c\n", ch);
//
//	ch = fgetc(pf); // d
//	printf("%c\n", ch);
//
//	// 写文件
//	// int fputc ( int character, FILE * stream );
//	//fputc('a', pf);
//	//fputc('b', pf);
//	//fputc('c', pf);
//	//fputc('d', pf);
//
//	/*for (int i = 0; i < 26; i++) {
//		fputc('a' + i, pf);
//		fputc('\n', pf);
//	}*/
//
//	// int fgetc ( FILE * stream );
//
//	// 关闭文件
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

// 写一个代码，完成将data1.txt文件的内容，拷贝一份生成data2.txt文件
// 文件拷贝

//#include <stdio.h>
//
//int main()
//{
//	FILE* pfread = fopen("data1.txt", "r");
//	if (pfread == NULL)
//	{
//		perror("fopen->data1.txt");
//		return 1;
//	}
//
//	FILE* pfwrite = fopen("data2.txt", "w");
//	if (pfwrite == NULL)
//	{
//		fclose(pfread);
//		pfread = NULL;
//
//		perror("fopen->data2.txt");
//		return 1;
//	}
//
//	// 数据的读写和拷贝
//	int ch = 0;
//	while ((ch = fgetc(pfread)) != EOF)
//	{
//		fputc(ch, pfwrite);
//	}
//
//	fclose(pfread);
//	fclose(pfwrite);
//
//
//	return 0;
//}

// int fputs ( const char * str, FILE * stream );
//#include <stdio.h>
//
//int main()
//{
//	FILE* pf = fopen("data.txt", "r");
//
//	if (pf == NULL)
//	{
//		return 1;
//	}
//
//	// 读取
//	// char* fgets(char* str, int num, FILE * stream);
//	char arr[20] = "xxxxxxxxxxxxxxxxxxx";
//	fgets(arr, 10, pf); // 最多复制num - 1位
//
//	//  写文件 - 写一行
//	//fputs("abcdef", pf);
//	//fputs("abcdef\n", pf);
//	//fputs("abcdef", pf);
//	//fputs("abcdef\n", pf);
//
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

// int fprintf ( FILE * stream, const char * format, ... );
// #include <stdio.h>
//
//struct Stu
//{
//	char name[20];
//	int age;
//	float score;
//};
//
//int main()
//{
//	struct Stu s = { 0 };
//
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		return 1;
//	}
//	// 写读文件
//	// fprintf(pf, "%s %d %.1f", s.name, s.age, s.score);
//	// int fscanf ( FILE * stream, const char * format, ... );
//
//	fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
//
//	fprintf(stdout, "%s %d %.1f\n", s.name, s.age, s.score);
//
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

// size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
// size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );